import { plugin, AMessage } from 'alemonjs'
import { oImages } from '../api'

import { cwd, initialmap } from '../config/metadata'
import { command } from '../config/command'
import panduan from '../lib/ChessDecides'
const as = new panduan()

/**
 * 游戏过程中所有数据
 * @param {Object} chessman 渲染后的地图
 * @param {Object} archive 双方棋子位置标记A,B,'0'
 * @param {Boolean} game 游戏是否开始
 * @param {Object} players 参与游戏的玩家编号
 * @param {Object} nickname 参与游戏的玩家昵称
 * @param {Object} current 参与游戏的玩家昵称
 */
const metadata = {}

// 初始地图，不可修改
const map = initialmap.chess
const rows = 8 // 棋盘宽度
const cols = 8 // 棋盘高度

export class Chess extends plugin {
  constructor() {
    super({
      dsc: '国际象棋',
      priority: 5000,
      rule: [...command.chess]
    })
  }

  /**
   * 认输
   */
  async ov(e: AMessage) {
    if (
      metadata[e.channel_id] &&
      metadata[e.channel_id].nickname[e.user_id] === e.user_name
    ) {
      // 判断玩家是否在游戏中
      const team = metadata[e.channel_id].players[e.user_id]
      // 对方组
      let isAB = '黑白'
      isAB = isAB.replace(new RegExp(team), '')
      e.reply(`恭喜${isAB}队获得胜利`)
      over(e)
    } else {
      e.reply(`你还没加入游戏，不能主动结束游戏`)
    }
  }

  /**
   * 发起游戏
   */
  async LaunchGame(e: AMessage) {
    if (!metadata[e.channel_id]) {
      await over(e)
    }
    const emsg = e.msg.match(/[黑白]/)
    const players = Object.values(metadata[e.channel_id].players).length
    // console.log(players);

    // 判断是否在游戏内
    if (metadata[e.channel_id].players[e.user_id]) {
      e.reply(
        '你已加入游戏，队伍：' + metadata[e.channel_id].players[e.user_id]
      )
      return
    }

    // 判断是玩家几
    if (players == 0) {
      metadata[e.channel_id].nickname[e.user_id] = e.user_name
      metadata[e.channel_id].players[e.user_id] = '黑'
      e.reply(
        `玩家${e.user_name}发起了国际象棋，其他成员可发送“加入国际象棋”加入游戏`
      )
    }
    if (players == 1) {
      metadata[e.channel_id].nickname[e.user_id] = e.user_name
      metadata[e.channel_id].players[e.user_id] = '白'

      const players_nickname = Object.keys(metadata[e.channel_id].players)

      const A = metadata[e.channel_id].players[players_nickname[0]]
      const B = metadata[e.channel_id].players[players_nickname[1]]

      e.reply([
        `本群游戏开始\n`,
        `${A}棋:${metadata[e.channel_id].nickname[players_nickname[0]]}\n`,
        `${B}棋:${metadata[e.channel_id].nickname[players_nickname[1]]}\n`,
        `${A}棋先手\n`,
        `其他成员可发送“加入国际象棋黑或白”加入指定队伍中`
      ])
      metadata[e.channel_id].current = '黑'
      await newgame(e)
    }
    if (players >= 2 && emsg[0]) {
      metadata[e.channel_id].nickname[e.user_id] = e.user_name
      metadata[e.channel_id].players[e.user_id] = emsg[0]
      e.reply(`玩家${e.user_name}加入队伍“${emsg[0]}”`)
    }
  }

  /**
   * 游戏指令
   */
  async game(e: AMessage) {
    if (!metadata[e.channel_id] || !metadata[e.channel_id].game) {
      e.reply('本群游戏未开始，请先发送“/发起国际象棋”')
      return false
    }

    // 判断玩家是否在游戏中
    const team = metadata[e.channel_id].players[e.user_id]
    if (!team) {
      e.reply(
        `你还没加入游戏，可发送”加入国际象棋黑或白“加入指定队伍中，即可操作游戏`
      )
      return false
    }
    // console.log("player：" + team)

    // 对方组
    let isAB = '黑白'
    isAB = isAB.replace(new RegExp(team), '')

    // 判断是否可操作
    if (team != metadata[e.channel_id].current) {
      e.reply(`当前不是你的回合`)
      return false
    }

    // 0：选择，1：目的地
    const msg = e.msg.toUpperCase() // 大写字母
    const emsg = msg.match(/([a-zA-Z])(\d+)[\s\S]?([a-zA-Z])(\d+)/)

    if (!emsg) {
      e.reply('指令不规范~请参考“/国际象棋帮助”')
      return false
    }

    // 选择
    const letter1 = emsg[1].charCodeAt(0) - 65 // 转数字 A = 0
    const num1 = emsg[2]
    const tp1 = `${letter1}-${num1}`

    // 目的地
    const letter2 = emsg[3].charCodeAt(0) - 65 // 转数字 A = 0
    const num2 = emsg[4]
    const tp2 = `${letter2}-${num2}`
    // console.log(tp1,tp2);

    // 判断移动是否正确
    const iscorrect = await as.Audit(
      e,
      [letter1, num1, letter2, num2],
      tp1,
      tp2,
      team,
      metadata
    )
    // console.log(iscorrect)
    if (!iscorrect || iscorrect[0] !== true) {
      e.reply(`移动不正确`)
      return
    }

    const target = metadata[e.channel_id].chessman[letter1 + '-' + num1]

    // 移动自己的棋子
    if (metadata[e.channel_id].archive[tp1] == team) {
      if (
        metadata[e.channel_id].chessman[tp2] &&
        metadata[e.channel_id].chessman[tp2] != team
      ) {
        // 清空原本位置，添加新的位置
        metadata[e.channel_id].chessman[tp1] = '空'
        metadata[e.channel_id].chessman[tp2] = target
        metadata[e.channel_id].archive[tp1] = '0'
        metadata[e.channel_id].archive[tp2] = team
        metadata[e.channel_id].current = isAB // 设置组
      }
      // 传入两个tp点
      await generate(e, tp1, tp2)
      // 胜利提示
      if (iscorrect[1] === true) {
        e.reply(`恭喜${team}队获得胜利`)
        over(e)
      }
    } else if (metadata[e.channel_id].archive[tp1] == '0') {
      // 移动空气
      e.reply('你不能操作棋盘中的空气：' + emsg[1] + emsg[2])
    } else {
      // 移动对方棋子
      e.reply('你不能操作对方的棋子')
    }
  }
}

/**
 * 新游戏
 */
async function newgame(e: AMessage) {
  const data_map1 = []
  // 遍历numbers，每x个数换一行
  for (let i = 0; i < map.length; i += rows) {
    data_map1.push(map.slice(i, i + rows))
  }

  // 初始化双方棋子
  for (const i in data_map1) {
    for (const j in data_map1[i]) {
      // 前排
      if (Number(i) == 0 || Number(i) == 1) {
        metadata[e.channel_id].archive[i + '-' + j] = '白'
      } else if (Number(i) == 6 || Number(i) == 7) {
        // 后排
        metadata[e.channel_id].archive[i + '-' + j] = '黑'
      } else {
        // 空位
        metadata[e.channel_id].archive[i + '-' + j] = '0'
      }
      metadata[e.channel_id].chessman[i + '-' + j] = data_map1[i][j]
    }
  }
  metadata[e.channel_id].game = true
  generate(e)
}

/**
 * 初始化游戏
 */
async function over(e: AMessage) {
  metadata[e.channel_id] = {}
  metadata[e.channel_id].chessman = {}
  metadata[e.channel_id].archive = {} // 双方棋子位置标记
  metadata[e.channel_id].game = false // 游戏是否正在运行
  metadata[e.channel_id].players = {} // 参与游戏的玩家
  metadata[e.channel_id].nickname = {} // 参与游戏的玩家
  metadata[e.channel_id].current = {} // 当前可操作的玩家
}

/**
 * 发送图片
 */
async function generate(e: AMessage, tp1?: string, tp2?: string) {
  let data_map = metadata[e.channel_id].chessman // 拉取地图数据
  const biaoji = String(Object.values(metadata[e.channel_id].archive)) // 获取双方棋子标记
  let ss = {} // 标记框
  let isAB: string
  if (metadata[e.channel_id].current === '白') {
    isAB = '黑box'
  } else {
    isAB = '白box'
  }
  // 设置标记框
  if (tp1 && tp2) {
    for (let i = 0; i < cols; i++) {
      for (let j = 0; j < rows; j++) {
        if (tp1 == `${i}-${j}` || tp2 == `${i}-${j}`) {
          ss[`${i}-${j}`] = isAB
        } else {
          ss[`${i}-${j}`] = '0'
        }
      }
    }
  }
  data_map = String(Object.values(data_map)) // 格式化地图
  ss = String(Object.values(ss)) // 格式化标记地图

  /**
   * map 地图
   */
  const data = {
    map: data_map,
    archive: biaoji,
    _res: cwd,
    ss: ss
  }
  const img = await oImages('/resources/html/国际象棋.html', data)
  if (img) e.reply(img)
  return false
}
